/** 
 * @defgroup prefs prefs
 * preference-file routines
 * @{
 */
 

#include <getopt.h>
#include <string.h>
#include "config.h"
#include "source.h"
#include "main.h"
#include "sensor.h"
#include "output.h"
#include "gui.h"
#include "prefs.h"


static int configfile_save(char *filename);

/** settings structure */
static struct Prefs
{
    char *xml_filename;
    xmlParserCtxtPtr xml_parser;
    xmlDocPtr xml_doc;
    xmlNodePtr root_node;
    int verbose, quiet;
}prefs;


/********************* getter/setter for local variables *********************/
/**
 * prefs.verbose getter
 */
int prefs_get_verbose()
{
    return prefs.verbose;
}
/**
 * util.verbose setter
 */
void prefs_set_verbose(int v)
{
    prefs.verbose = v;
}
/**
 * prefs.quiet getter
 */
int prefs_get_quiet()
{
    return prefs.quiet;
}
/**
 * prefs.quiet setter
 */
void prefs_set_quiet(int q)
{
    prefs.quiet = q;
}

/**
 * xml-doc ptr getter
 */
xmlDocPtr prefs_get_xmlDoc()
{
    if(!(prefs.xml_doc))
        _VERBOSE3 printf("%s(): returned NULL pointer!\n", __func__);
    return prefs.xml_doc;
}

/**
 * @todo implement
 */
static void prefs_print_help(char *name)
{
    printf("help!\n");
}

/************************** GTK-Callbacks **************************/
/**
 * user wants to save the config to a file
 */
gboolean cb_prefs_save_file(GtkWidget * widget)
{
    _VERBOSE2 printf("%s()\n", __func__);
    configfile_save(prefs.xml_filename);
    return TRUE;
}

/************************** Module **************************/
/**
 * parse arguments using getopt.h
 * @param argc - argument count
 * @param argv - argument array
 */
static void args_parse(int argc, char *argv[])
{
    static struct option cmdline_options[] = {
        {"help", 0, 0, 'h'},
        {"verbose", 0, 0, 'v'},
        {"quiet", 0, 0, 'q'},
        {0, 0, 0, 0}
    };
    int cmdline_argument_index = 0;
    int cmdline_argument;

    
    _VERBOSE2 printf("%s()\n", __func__);
    
    /* reset verbosity */
    prefs_set_verbose(0);
    
    while (1) {
        cmdline_argument =
            getopt_long(argc, argv, "-hvq", cmdline_options,
                        &cmdline_argument_index);
        if(cmdline_argument == -1)
            break;

        switch (cmdline_argument) {
            /*
             * increase verbosity 
             */
        case 'v':
            prefs_set_verbose(prefs_get_verbose()+1);
            _VERBOSE1 printf("** verbosity level %d\n", prefs_get_verbose());
            break;

            /*
             * print help message 
             */
        case 'h':
            prefs_print_help(argv[0]);
            break;

        case 'q':
            prefs_set_quiet(TRUE);
            break;

            /*
             * eek! unrecognized cmdline option 
             */
        default:
            break;
        }
    }
}

/**
 * simple file-copy 
 */
static int file_copy(char *source, char *dest)
{
#define BUFSIZE 1024
    FILE *src = NULL, *dst = NULL;
    char *buffer = NULL;
    size_t written, toWrite = BUFSIZE;

    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if((src = fopen(source, "r"))) {

        if((dst = fopen(dest, "w"))) {
            
            if((buffer = malloc(BUFSIZE))) {

                while (!feof(src)) {
                    
                    toWrite = fread(buffer, 1, BUFSIZE, src);

                    if(toWrite == 0) {
                        perror("fread():");
                        break;
                    }

                    written = fwrite(buffer, 1, toWrite, dst);
                    if(written == 0) {
                        perror("fwrite():");
                        break;
                    }
                }
            }

            /*
             * no memory 
             */
            else {
                printf("No memory to copy file.\n");
                return -1;
            }
        }

        /*
         * failed to open dest-file 
         */
        else {
            printf("Failed to open dest-file: \"%s\"\n", source);
            perror("fopen");
            return -1;
        }
    }

    /*
     * failed to open source-file 
     */
    else {
        printf("Failed to open source-file: \"%s\"\n", source);
        perror("fopen");
        return -1;
    }

    if(src)
        fclose(src);
    if(dst)
        fclose(dst);
    if(buffer)
        free(buffer);

    return 0;
}

/**
 * opens xml-config file and find root-node,
 * copy default config if no file exists
 */
static int configfile_open()
{
    char tmpstring[1024];
    char tmpstring2[1024];
    struct stat status;
        
    _VERBOSE1 printf("%s(): \"%s\"\n", __func__, prefs.xml_filename);

    /*
     * new xml-parser 
     */
    if((prefs.xml_parser = xmlNewParserCtxt())) 
    {
        
        /*
         * parse xml-file 
         */
        if(prefs.xml_filename) 
        {
            if((prefs.xml_doc = xmlCtxtReadFile(prefs.xml_parser,
                                                  prefs.xml_filename, NULL,
                                                  XML_PARSE_DTDVALID |
                                                  XML_PARSE_DTDLOAD |
                                                  XML_PARSE_DTDATTR)))
            {
                /*
                 * check for validity 
                 */
                if(prefs.xml_parser->valid) 
                {
                    _VERBOSE1 printf("%s(): xml is valid\n", __func__);

                    /*
                     * get root-node 
                     */
                    if(!(prefs.root_node =
                        xmlDocGetRootElement(prefs.xml_doc)))
                    {
                        _VERBOSE1 printf("%s(): Could not find root-node in \"%s\"",
                                         __func__, prefs.xml_filename);

                        return -1;
                    }
                }
                else {
                    _VERBOSE1
                        printf("%s(): Config-file (%s) did not pass validation.\n",
                               __func__, prefs.xml_filename);

                    return -1;
                }
            }
            
            /* could not read file, copy default config */
            else 
            {
                _VERBOSE1
                    printf
                    ("%s(): Error opening \"%s\" ... Trying to copy default one.\n",
                     __func__, prefs.xml_filename);
                
                /* build dir-name */
                snprintf((char *) &tmpstring, 254, "%s/.lasertraq", getenv("HOME"));
                
                /* check if ~/.lasertraq directory exists */
                if(stat((char *) &tmpstring, &status) != 0) {
                    /* nothing? - create dir */
                    if((mkdir((char *) &tmpstring, 0700)) < 0) {
                        printf("%s(): FATAL_ERROR: failed to create \"%s\"\n",
                            __func__, (char *) &tmpstring);
                        perror("mkdir");
                        return -1;
                    }
                    else {
                        /*
                         * tell that dir has been created 
                         */
                        _VERBOSE1 printf("%s(): Created directory \"%s\" ...\n", 
                            __func__, (char *) &tmpstring);
                    }
                }
                /*
                 * stat() suceeded, now see what we've got 
                 */
                else {
                    /*
                     * exists and is directory ? 
                     */
                    if((status.st_mode & S_IFDIR) == 1) {
                        printf("%s(): FATAL_ERROR: \"%s\" exists but is no directory (please delete)...\n",
                                __func__, (char *) &tmpstring);
                        return -1;
                    }
                }
                
                /*
                 * build filename of src-file 
                 */
                snprintf((char *) &tmpstring, 254, "%s/%s/lt.dtd",
                         DATADIR, PACKAGE);
                /*
                 * build dest-file name 
                 */
                snprintf((char *) &tmpstring2, 254, "%s/.lasertraq/lt.dtd",
                         getenv("HOME"));

                if(file_copy((char *) &tmpstring, (char *) &tmpstring2) < 0) {
                    printf("%s(): Failed to copy default-config.\n", __func__);
                    return -1;
                }

                
                
                /*
                 * build filename of src-file 
                 */
                snprintf((char *) &tmpstring, 254, "%s/%s/config.xml",
                         DATADIR, PACKAGE);
                /*
                 * build dest-file name 
                 */
                snprintf((char *) &tmpstring2, 254,
                         "%s/.lasertraq/config.xml", getenv("HOME"));
                if(file_copy((char *) &tmpstring, (char *) &tmpstring2) < 0) {
                    printf("%s(): Failed to copy default-config.\n", __func__);
                    return -1;
                }
                
                /* retry config-load */
                if(configfile_open() < 0) {
                    printf("%s(): Failed to parse config for the 2nd time." \
                        "Default-config corrupted?\n", __func__);
                    return -1;
                }
            }
        }
        else {
            _VERBOSE1
                printf("%s(): XML-Filename is NULL. Please contact developer.\n",
                        __func__);

            return -1;
        }
    }
    else {
        _VERBOSE1 printf("%s(): Failed to create xml-context. (libxml-error)\n",
                    __func__);
        return -1;
    }
    return 0;
}

/**
 * get xml sub-node from parent node-name
 */
xmlNodePtr prefs_xmlNode_find(char *nodeName, xmlDocPtr doc, xmlNode * node)
{
    xmlNode *tempNode, *resultNode = NULL, *nextChild;

    _VERBOSE2 printf("get_xml_node(): looking for \"%s\" in \"%s\"\n",
                        nodeName, node->name);

    /*
     * main search-loop 
     */
    for(tempNode = node; tempNode && resultNode == NULL;
        tempNode = tempNode->next) {
        /*
         * check if we really got a node 
         */
        if(tempNode->type == XML_ELEMENT_NODE) {
            // _VERBOSE2 printf(" -> %s\n", tempNode->name);
            /*
             * check if it's our node we found 
             */
            if(xmlStrcmp(tempNode->name, (const xmlChar *) nodeName) == 0) {
                resultNode = tempNode;
                break;
            }
            /*
             * check possible childs of node... 
             */
            for(nextChild = xmlGetLastChild(tempNode);
                nextChild && resultNode == NULL;
                nextChild = nextChild->prev) {
                // _VERBOSE2 printf(" --> %s\n", nextChild->name);
                /*
                 * check if current node is the one 
                 */
                if(xmlStrcmp(nextChild->name, (const xmlChar *) nodeName) ==
                   0) {
                    // _VERBOSE2 printf(" found...\n");
                    resultNode = nextChild;
                }
                else {
                    resultNode = prefs_xmlNode_find(nodeName, doc, nextChild);
                }
            }
        }
    }
    if(resultNode == NULL) {
        // _VERBOSE6 printf("Node \"%s\" not found in \"%s\"...\n", nodeName, 
        // 
        // 
        // node->name);
        return NULL;
    }
    else {
        // _VERBOSE6 printf("found in \"%s\"...\n", node->name);
        return (xmlNodePtr) (resultNode);
    }
}


/**
 * create structure from xml-data 
 */
static int configfile_parse()
{
    xmlNode *tmp_node;
    
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if (prefs.root_node)
    {
        
        
        /* get glade filename */
        gui_set_gladefile(strdup(
            (char *) xmlGetProp(prefs.root_node, (xmlChar *) "gladefile")));
        
     
        /*
         * walk whole xml-tree and register stuff 
         */
        for(tmp_node = prefs.root_node->xmlChildrenNode; tmp_node;
            tmp_node = tmp_node->next) 
        {
            /*
             * got a node? 
             */
            if(tmp_node->type == XML_ELEMENT_NODE) {
                _VERBOSE4 printf("%s: node \"%s\"\n", __func__, tmp_node->name);
    
                
                /*
                 * video-source node? 
                 */
                if(xmlStrcmp(tmp_node->name, (xmlChar *) "video-source") == 0) 
                {
                    
                    /*
                     * init video-source node
                     */
                    if(!(src_init_from_xml(tmp_node)))
                    {
                        gui_dialog("Failed to initialize source \"%s\"\n",
                                 xmlGetProp(tmp_node, (xmlChar *) "name"));
                        return FALSE;
                    }
                }
            }
        }
    
        /* got at least one source? */
        if(src_get())
            return 0;
        else
        {
            _ERROR printf("%s(): Couldn't find any source!\n", __func__);
            return -1;
        }
    }
    else
    {
        _ERROR printf("%s(): No root-node!\n", __func__);
    }
    
    return -1;
}

/**
 * dump settings to xml-file 
 */
static int configfile_save(char *filename)
{
#define XML_BUFFERSIZE 4096
    char *xml_buffer;
    struct video_src *tmp_src;
    struct sensor *tmp_sensor;
    xmlNode *tmp_src_xml, *tmp_sensor_xml, *tmp_field_xml, *tmp_color_xml;
    int error = TRUE;
    char tmpstring[1024];
    xmlChar *save_buffer;
    int filesize;
    FILE *prefs_file;
    xmlDtd *dtd;

    _VERBOSE2 printf("%s()\n", __func__);
    
    if((xml_buffer = calloc(1, XML_BUFFERSIZE))) {
        /*
         * free current xml-prefs 
         */
        if(prefs.xml_doc)
            xmlFreeDoc(prefs.xml_doc);
        if(prefs.xml_parser)
            xmlFreeParserCtxt(prefs.xml_parser);

        /*
         * build up new xml-prefs 
         */
        if((prefs.xml_parser =
            (xmlParserCtxtPtr) xmlCreateMemoryParserCtxt(xml_buffer,
                                                         XML_BUFFERSIZE))) {
            /*
             * init new xml-document 
             */
            prefs.xml_doc = xmlNewDoc(BAD_CAST "1.0");
            dtd =
                xmlNewDtd(prefs.xml_doc, (xmlChar *) "lasertraq",
                          (xmlChar *) "SYSTEM", (xmlChar *) "lt.dtd");
            prefs.xml_doc->intSubset = dtd;
            dtd->doc = prefs.xml_doc;
            dtd->parent = prefs.xml_doc;
            prefs.xml_doc->children = (xmlNodePtr) dtd;

            prefs.root_node = xmlNewNode(NULL, BAD_CAST "lasertraq");
            xmlNewProp(prefs.root_node, BAD_CAST "version",
                       BAD_CAST PREFS_VERSION);
            xmlNewProp(prefs.root_node, BAD_CAST "gladefile",
                        BAD_CAST gui_get_gladefile());
                                                             
            xmlNewNs(prefs.root_node, NULL, NULL);
            xmlDocSetRootElement(prefs.xml_doc, prefs.root_node);

            /*
             * save all sources 
             */
            for(tmp_src = src_get_first(); tmp_src;
                tmp_src = tmp_src->next_source) 
            {
                
                /*
                 * create source-node 
                 */
                tmp_src_xml =
                    xmlNewChild(prefs.root_node, NULL,
                                BAD_CAST "video-source", NULL);

                /*
                 * add name 
                 */
                xmlNewProp(tmp_src_xml, BAD_CAST "name",
                           BAD_CAST tmp_src->name);
                /*
                 * add gstreamer-string 
                 */
                xmlNewProp(tmp_src_xml, BAD_CAST "gst_string",
                           BAD_CAST tmp_src->gst_string);
                /*
                 * add tuner (if there is one) 
                 */
                if(tmp_src->tuner)
                    xmlNewProp(tmp_src_xml, BAD_CAST "tuner",
                               BAD_CAST tmp_src->tuner);

                /* add swap-rb flag */
                snprintf((char *) &tmpstring, 1023, "%d", tmp_src->swap_rb);
                xmlNewProp(tmp_src_xml, BAD_CAST "swap-rb",
                                BAD_CAST &tmpstring);
                
                /* add disabled flag */
                snprintf((char *) &tmpstring, 1023, "%d", tmp_src->disabled);
                xmlNewProp(tmp_src_xml, BAD_CAST "disabled",
                                BAD_CAST &tmpstring);
                
                /*
                 * add sensors 
                 */
                for(tmp_sensor = tmp_src->first_sensor; tmp_sensor;
                    tmp_sensor = tmp_sensor->next_sensor) 
                {
                    
                    tmp_sensor_xml =
                        xmlNewChild(tmp_src_xml, NULL, BAD_CAST "sensor",
                                    NULL);
                    /*
                     * add name 
                     */
                    xmlNewProp(tmp_sensor_xml, BAD_CAST "name",
                               BAD_CAST tmp_sensor->name);

                    /** add delay */
                    snprintf((char *) &tmpstring, 1023, "%d", tmp_sensor->ondelay);
                    xmlNewProp(tmp_sensor_xml, BAD_CAST "on_delay",
                                BAD_CAST &tmpstring);
                    
                    snprintf((char *) &tmpstring, 1023, "%d", tmp_sensor->offdelay);
                    xmlNewProp(tmp_sensor_xml, BAD_CAST "off_delay",
                                BAD_CAST &tmpstring);
    
                    snprintf((char *) &tmpstring, 1023, "%d",tmp_sensor->repeat_delay);
                    xmlNewProp(tmp_sensor_xml, BAD_CAST "repeat_delay",
                                BAD_CAST &tmpstring);
                                
                    /*
                     * add output-node 
                     */
                    tmp_field_xml =
                        xmlNewChild(tmp_sensor_xml, NULL, BAD_CAST "output",
                                    NULL);
                    /*
                     * output-type 
                     */
                    switch (tmp_sensor->out_type) {
                        case OUT_TYPE_MOUSE:
                            xmlNewProp(tmp_field_xml, BAD_CAST "type",
                                       BAD_CAST "mouse");
                            snprintf((char *) &tmpstring, 254, "%d",
                                     tmp_sensor->out_width);
    
                            /*
                             * mouse-node 
                             */
                            tmp_color_xml =
                                xmlNewChild(tmp_field_xml, NULL, BAD_CAST "mouse",
                                            NULL);
                            xmlNewProp(tmp_color_xml, BAD_CAST "width",
                                       BAD_CAST & tmpstring);
                            snprintf((char *) &tmpstring, 254, "%d",
                                     tmp_sensor->out_height);
                            xmlNewProp(tmp_color_xml, BAD_CAST "height",
                                       BAD_CAST & tmpstring);
                            snprintf((char *) &tmpstring, 254, "%d",
                                     tmp_sensor->buttonmask);
                            xmlNewProp(tmp_color_xml, BAD_CAST "buttonmask",
                                       BAD_CAST & tmpstring);
                            break;
    
                        case OUT_TYPE_KEY:
                            xmlNewProp(tmp_field_xml, BAD_CAST "type",
                                       BAD_CAST "keyboard");
    
                            /*
                             * keyboard-node 
                             */
                            tmp_color_xml =
                                xmlNewChild(tmp_field_xml, NULL,
                                            BAD_CAST "keyboard", NULL);
                        
                            /* save key */
                            xmlNewProp(tmp_color_xml, BAD_CAST "key",
                                       BAD_CAST
                                       sensor_key_string(tmp_sensor->out_key));
                        
                            /* save menu-entry */
                            snprintf((char *) &tmpstring, 254, "%d", tmp_sensor->out_key);
                            xmlNewProp(tmp_color_xml, BAD_CAST "menu-entry",
                                        BAD_CAST &tmpstring);
                                        
                            
                            break;
    
                        /*
                         * program-node
                         */
                        case OUT_TYPE_EXE:
                            xmlNewProp(tmp_field_xml, BAD_CAST "type",
                                       BAD_CAST "execute");
                        
                            tmp_color_xml = 
                                xmlNewChild(tmp_field_xml, NULL, BAD_CAST
                                    "program", NULL);
                            
                            xmlNewProp(tmp_color_xml, BAD_CAST "path",
                                    BAD_CAST tmp_sensor->out_program);
                        
                            break;
                        
                        default:
                            gui_dialog("Unsupported output-type...\n");
                            break;
                    }

                    /*
                     * add field-node 
                     */
                    tmp_field_xml =
                        xmlNewChild(tmp_sensor_xml, NULL, BAD_CAST "field",
                                    NULL);
                    /*
                     * add coordinates 
                     */
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_x1);
                    xmlNewProp(tmp_field_xml, BAD_CAST "x1",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_x2);
                    xmlNewProp(tmp_field_xml, BAD_CAST "x2",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_x3);
                    xmlNewProp(tmp_field_xml, BAD_CAST "x3",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_x4);
                    xmlNewProp(tmp_field_xml, BAD_CAST "x4",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_y1);
                    xmlNewProp(tmp_field_xml, BAD_CAST "y1",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_y2);
                    xmlNewProp(tmp_field_xml, BAD_CAST "y2",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_y3);
                    xmlNewProp(tmp_field_xml, BAD_CAST "y3",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->wrp_y4);
                    xmlNewProp(tmp_field_xml, BAD_CAST "y4",
                               BAD_CAST & tmpstring);

                    /*
                     * add color-node 
                     */
                    tmp_color_xml =
                        xmlNewChild(tmp_sensor_xml, NULL, BAD_CAST "color",
                                    NULL);
                    snprintf((char *) &tmpstring, 254, "%.2f",
                             tmp_sensor->thr_threshold);
                    xmlNewProp(tmp_color_xml, BAD_CAST "threshold",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->thr_R);
                    xmlNewProp(tmp_color_xml, BAD_CAST "R",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->thr_G);
                    xmlNewProp(tmp_color_xml, BAD_CAST "G",
                               BAD_CAST & tmpstring);
                    snprintf((char *) &tmpstring, 254, "%d",
                             tmp_sensor->thr_B);
                    xmlNewProp(tmp_color_xml, BAD_CAST "B",
                               BAD_CAST & tmpstring);
                }
            }

            /*
             * save file 
             */
            xmlDocDumpFormatMemoryEnc(prefs.xml_doc, &save_buffer,
                                      &filesize, "ISO-8859-1", 1);

            /*
             * save xml-file 
             */
            prefs_file = fopen(filename, "w");
            if(prefs_file) {
                if(fwrite((char *) save_buffer, filesize, 1, prefs_file) <= 0)
                {
                   gui_dialog("Failed to fwrite() file: \"%s\"\n", filename,
                              strerror(errno));
                }
                fclose(prefs_file);
            }
            else {
                gui_dialog("Could not open \"%s\" for writing...\n", filename);
                error = FALSE;
            }
            xmlFree(save_buffer);
        }
        else
            error = FALSE;
    }
    else
        error = FALSE;

    return error;
}



/**
 * initialize everything for this module
 */
int prefs_init(int argc, char *argv[])
{
    char *home_dir;
    
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    /* clear module-wide structure */
    memset(&prefs, 0, sizeof(struct Prefs));
        
    /*
     * create xml-config filename 
     */
    if(!(prefs.xml_filename = calloc(1, 1024))) {
        printf("%s(): Not enough memory...\n", __func__);
        return -1;
    }
    
    if(!(home_dir = getenv("HOME"))) {
        printf("%s(): $HOME not set... Where is the config-file?\n", __func__);
        return -1;
    }

    snprintf(prefs.xml_filename, 1023, "%s/.lasertraq/config.xml", home_dir);
    
    
    
    /*
     * parse commandline arguments 
     */
    args_parse(argc, argv);
    
    
    /*
     * check for xml-config 
     */
    if(configfile_open() < 0)
    {
        _VERBOSE1 printf("Failed to init config-file...\n");
        return -1;
    }
    

    /*
     * init video-source 
     */
    if(configfile_parse() < 0)
    {
        _VERBOSE1 printf("Failed to parse config-file...\n");
        return -1;
    }
    
    return 0;
}


/**
 * initialize settings-related gui
 */
int prefs_gui_init()
{
    /*g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "menuitem_save")), "activate",
                     G_CALLBACK(cb_prefs_save_file), NULL);*/

    
    return 0;
}

/**
 * cleanup everything for this module
 */
void prefs_cleanup()
{
    /*
     * free stuff 
     */
    free(prefs.xml_filename);
    xmlFreeParserCtxt(prefs.xml_parser);
    xmlFreeDoc(prefs.xml_doc);
    
    prefs.xml_filename = NULL;
    prefs.xml_parser = NULL;
    prefs.xml_doc = NULL;
}

/** 
 * @} 
 */
